package roborally.model;

/**
 * An enumeration of orientations.
 * 
 * @version  1.0
 * @author  Pieter Robberechts	(1e Bach Informatica)
 * @author	Jeroen Sanders		(1e Bach Informatica)
 *  
 */
public enum Orientation {
	
	UP(0){
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in counterclockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == LEFT
		 */
		public Orientation turn90CounterClockwise() {
			return LEFT;
		}
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in clockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == RIGHT
		 */
		public Orientation turn90Clockwise(){
			return RIGHT;
		}

	}, 
	
	RIGHT(1){
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in counterclockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == UP
		 */
		public Orientation turn90CounterClockwise() {
			return UP;
		}
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in clockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == DOWN
		 */
		public Orientation turn90Clockwise(){
			return DOWN;
		}
		
	}, 
	
	DOWN(2){
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in counterclockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == RIGHT
		 */
		public Orientation turn90CounterClockwise() {
			return RIGHT;
		}
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in clockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == LEFT
		 */
		public Orientation turn90Clockwise(){
			return LEFT;
		}
		
	}, 
	
	LEFT(3){
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in counterclockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == DOWN
		 */
		public Orientation turn90CounterClockwise() {
			return DOWN;
		}
		
		/**
		 * Return the resulting orientation when an object is turned 90 degrees 
		 * in clockwise direction, starting from this orientation.
		 *
		 * @return	...
		 * 			| result == UP
		 */
		public Orientation turn90Clockwise(){
			return UP;
		}
		
	};

	/**
	 * Initialize this new orientation with a given number, representing this orientation.
	 * 
	 * @param	number
	 * 			The number which is associated with this new orientation.
	 * @post	...
	 * 			| new.getNumber == number
	 */
	private Orientation(int number){
		this.number = number;
	}
	
	/**
	 * Variable registering a number, associated with an orientation.
	 */
	private final int number;
	
	/**
	 * Return the resulting orientation when an object is turned 90 degrees 
	 * in the given direction, starting from this orientation.
	 *
	 * @return	...
	 * 			| if direction == Direcion.COUNTER_CLOCKWISE
	 * 			| 	then result == turn90CounterClockwise()
	 * 			| if direction == Direction.CLOCKWISE
	 * 			| 	then result == turn90Clockwise()
	 * @return	...
	 * 			| if direction != Direcion.COUNTER_CLOCKWISE && direction != Direction.CLOCKWISE
	 * 			|	then result == this
	 */
	public Orientation turn90(Direction direction){
		if(direction == Direction.COUNTER_CLOCKWISE)
			return turn90CounterClockwise();
		else if(direction == Direction.CLOCKWISE)
			return turn90Clockwise();
		else
			return this;
	}
	
	/**
	 * Return the resulting orientation when an object is turned 90 degrees 
	 * in counterclockwise direction, starting from this orientation.
	 */
	public abstract Orientation turn90CounterClockwise(); 
	
	/**
	 * Return the resulting orientation when an object is turned 90 degrees 
	 * in clockwise direction, starting from this orientation.	
	 */
	public abstract Orientation turn90Clockwise();

	/**
	 * Return the corresponding orientation given a number.
	 * 
	 * @param	number
	 * 			A number which is associated with an orientation.
	 * @return	...
	 * 			| for one orientation in Orientation.values():
	 * 			| 	if(orientation.getNumber() == number)
	 * 			|		then result == orientation
	 * @return	...
	 * 			| for each orientation in Orientation.values():
	 * 			| 	if(orientation.getNumber() != number)
	 * 			|		then result == UP
	 */
	public static Orientation getConstant(int number) {
		for(Orientation orientation : Orientation.values()){
			if(orientation.getNumber() == number)
				return orientation;
		}
		return UP;
	}
	
	/**
	 * Return the number which is associated with the orientation.
	 */
	public int getNumber(){
		return number;
	}
}
